using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using WebSocketSharp;
using WebSocketSharp.Server;
using System.Net;
using System;
using HybridCLR.Editor.Commands;
using System.IO;
using System.Net.NetworkInformation;
using System.Linq;
using System.Reflection;

#if UNITY_EDITOR
[InitializeOnLoad]
public class HotUpdateManager : EditorWindow
{
    private static WebSocketServer wsServer;
    private static bool isServerRunning = false;

    static HotUpdateManager()
    {
        StartServer();
    }

    [MenuItem("Window/WebSocket Editor Window")]
    public static void ShowWindow()
    {
        GetWindow(typeof(HotUpdateManager));
    }

    void OnGUI()
    {
        GUILayout.Label("WebSocket Server Control", EditorStyles.boldLabel);

        if (GUILayout.Button(isServerRunning ? "Stop Server" : "Start Server"))
        {
            ToggleServer();
        }
    }

    private static void ToggleServer()
    {
        if (isServerRunning)
        {
            StopServer();
        }
        else
        {
            StartServer();
        }
    }

    public static void StartServer()
    {
        if (wsServer != null && wsServer.IsListening)
        {
            Debug.Log("WebSocket server is already running. Stopping the existing server.");
            wsServer.Stop();
            isServerRunning = false;
        }

        if (!isServerRunning)
        {
            IPAddress ipAddress;
            IPAddress.TryParse("0.0.0.0", out ipAddress);
            wsServer = new WebSocketServer(ipAddress, 3000);
            wsServer.AddWebSocketService<MyService>("/myService");
            wsServer.AddWebSocketService<Echo>("/echo");
            wsServer.Start();
            Debug.Log("WebSocket server started on port 3000");
            isServerRunning = true;
            WebSocketClient.Say();
        }
        
    }

    public static void StopServer()
    {
        if (wsServer != null && wsServer.IsListening)
        {
            wsServer.Stop();
            Debug.Log("WebSocket server stopped");
        }
        isServerRunning = false;
    }

    private static void RestartServer()
    {
        StopServer();
        StartServer();
    }

    void OnDestroy()
    {
        StopServer();
    }

    private static void KillProcessUsingPort(int port)
    {
        try
        {
            var startInfo = new System.Diagnostics.ProcessStartInfo
            {
                FileName = "cmd",
                Arguments = $"/c netstat -ano | findstr :{port}",
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (var process = System.Diagnostics.Process.Start(startInfo))
            {
                using (var reader = process.StandardOutput)
                {
                    string result = reader.ReadToEnd();
                    var lines = result.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (var line in lines)
                    {
                        var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (parts.Length > 4)
                        {
                            var pid = parts[parts.Length - 1];
                            //KillProcessById(pid);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Debug.LogError($"Failed to kill process using port {port}: {ex.Message}");
        }
    }

    private static void KillProcessById(string pid)
    {
        try
        {
            var startInfo = new System.Diagnostics.ProcessStartInfo
            {
                FileName = "cmd",
                Arguments = $"/c taskkill /PID {pid} /F",
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (var process = System.Diagnostics.Process.Start(startInfo))
            {
                process.WaitForExit();
                Debug.Log($"Killed process with ID {pid} ");
            } 
        }
        catch (Exception ex)
        {
            Debug.LogError($"Failed to kill process with ID {pid}: {ex.Message}");
        }
    }
}


public class MyService : WebSocketBehavior
{
    protected override void OnOpen()
    {
        base.OnOpen();
        Debug.Log($"Client connected: {Context.UserEndPoint}");
    }

    protected override void OnMessage(MessageEventArgs e)
    {
        Debug.Log("Received message: " + e.Data);
        if (e.Data == "RefreshAssets")
        {
            EditorApplication.delayCall += () =>
            {
                Debug.Log("Refreshing Asset Database...");
                AssetDatabase.Refresh();
                Send("Assets refreshed");
            };
        }
        if (e.Data == "CompileHotUpdate")
        {
            EditorApplication.delayCall += () =>
            {
                try
                {
                    Debug.Log("Starting compilation on the main thread...");
                    // 现在，我们在主线程中获取 activeBuildTarget
                    BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
                    CompileDllCommand.CompileDll(target);
                    Debug.Log("Compilation successful!");
                    // Move the compiled DLL to the target directory
                    MoveAndRenameDll(target);
                    Send("CompileSuccess");
                    //WebSocketClient.Say();
                }       
                catch (Exception ex)
                {
                    Debug.LogError("Compilation failed: " + ex.Message);
                    Send("CompileFailed: " + ex.Message);
                } 
            };
        }
        if (e.Data.StartsWith("MakePrefabs")){ 
            string name = e.Data.Split(":")[1];
            string sprite_name = e.Data.Split(":")[2];
            if (sprite_name == "None"){
                sprite_name = null;
            }
            EditorApplication.delayCall += () => {
                try{
                    Debug.Log("Starting make prefabs and pack up : " + name);
                    string assemblyPath = "Assets/HotUpdate/DLLs/HotUpdate.dll.bytes";
                    Assembly hotUpdateAssembly = Assembly.LoadFrom(assemblyPath);

                    // 使用反射获取类型
                    Type findTargetType = hotUpdateAssembly.GetType(name+"FindTarget");
                    Type influenceType = hotUpdateAssembly.GetType(name+"Influence");
                    Type startConditionType = hotUpdateAssembly.GetType(name+"StartCondition");

                    Debug.Log(findTargetType);
                    Debug.Log(influenceType);
                    Debug.Log(startConditionType);
                    if (findTargetType == null || influenceType == null || startConditionType == null){
                        Send("MakePrefabsFailed: " + "Failed to find types. Make sure you have successfully and currently edited the scripts: "+
                        name+"FindTarget.cs, "+name+"Influence.cs, "+name+"StartCondition.cs"+
                        ", and compiled."+
                        "Also, make sure the 'name' parameter is correct, which means the same as the Prefix of the types. Like 'Rock' is the name of RockGurouce, with type 'RockFindTargets'");
                        return;
                    }

                    
                    GurouceMaker.Make(name, findTargetType,influenceType,startConditionType, spriteName : sprite_name);
                    
                    Send("Prefabs made successfully");
                }catch (Exception ex){
                    Debug.LogError("Make prefabs failed: " + ex.Message);
                    Send("MakePrefabsFailed: " + ex.Message);

                }
            }; 
        }
    }

    private static void MoveAndRenameDll(BuildTarget target){
        string projectRoot = Application.dataPath.Replace("/Assets", "");
        string sourcePath = Path.Combine(projectRoot, "HybridCLRData/HotUpdateDlls", target.ToString(), "HotUpdate.dll");
        string targetPath = Path.Combine(projectRoot, "Assets/HotUpdate/DLLs/HotUpdate.dll.bytes");

        try
        {
            if (File.Exists(sourcePath))
            {
                // 确保目标目录存在
                Directory.CreateDirectory(Path.GetDirectoryName(targetPath));

                // 如果目标文件已存在，则删除
                if (File.Exists(targetPath))
                {
                    File.Delete(targetPath);
                    Debug.Log("Existing target file deleted.");
                }

                // 移动并重命名文件
                File.Move(sourcePath, targetPath);
                Debug.Log("DLL moved and renamed successfully!");
            }
            else
            {
                Debug.LogError("Source DLL not found: " + sourcePath);
            }
        }
        catch (System.Exception ex)
        {
            Debug.LogError("Error moving and renaming DLL: " + ex.Message);
        }
    }
}

public class Echo : WebSocketBehavior
{
  protected override void OnMessage(MessageEventArgs e)
  {
    Debug.Log("Received message: " + e.Data);
    Send(e.Data);
  }
}

#endif




